package com.jddup.program.comparator.postgresql;

import com.jddup.common.pojo.EntityAndDbDifference;
import com.jddup.common.pojo.TableColumn;
import com.jddup.program.comparator.DataTypeCompatibility;
import com.jddup.program.utils.Misc;

import java.util.ArrayList;

/**
 * Created by ZZB on 2017/12/11.
 */
public class PostgresqlDataTypeCompatibility implements DataTypeCompatibility {
    private static final String ALTER_SQL = "ALTER TABLE {tableName} ALTER  COLUMN {columnName} TYPE {columnType} ;";

    @Override
    public void compare(EntityAndDbDifference difference, TableColumn entityColumn, TableColumn tableColumn) {
        String tableName = difference.getTableName();
        String entityColumnName = entityColumn.getColumnName();
        String entityColumnType = entityColumn.getColumnType();
        String entityTypeFullName = entityColumn.getTypeFullName();
        String tableColumnType = tableColumn.getColumnType();
        if (entityColumnType.equals("VARCHAR")) {
            if (!tableColumnType.equals("VARCHAR") && !tableColumnType.equals("TEXT") && !tableColumnType.equals("CHAR"))
                notSame(difference,entityColumn,tableColumn);
            else if (Misc.isNotZero(entityColumn.getMaxLength()) && Misc.isNotZero(tableColumn.getMaxLength())
                    && entityColumn.getMaxLength() > tableColumn.getMaxLength()){
                putIntoDifference(difference,getAlterSQL(EntityAndDbDifference.ModifyDDL.LevelEnums.serious,tableName, entityColumnName, entityTypeFullName,"数据库中[" + entityColumnName + "]字段长度为[" + tableColumn.getMaxLength() +
                        "]比实体中约定最大长度[" + entityColumn.getMaxLength() + "]小！请修改实体字段或者执行以下SQL！"),entityColumnName);

            }
            else if (entityColumnType.equals("VARCHAR") && Misc.isNotZero(entityColumn.getMaxLength()) &&
                    entityColumn.getMaxLength() < 255 && tableColumnType.equals("TEXT")){
                putIntoDifference(difference,
                        getAlterSQL(EntityAndDbDifference.ModifyDDL.LevelEnums.optimized,tableName, entityColumnName, entityTypeFullName,"数据库中[" + entityColumnName + "]字段长度为[" + tableColumn.getMaxLength() +
                                "]比实体中约定最大长度[" + entityColumn.getMaxLength() +
                                "]大！修改实体字段或者执行以下SQL可以优化数据库性能！"),entityColumnName);

            }
        }  else if(entityColumnType.equals("INT2")){
            if(!tableColumnType.equals("INT2") && !tableColumnType.equals("INT4") && !tableColumnType.equals("INT8") &&
                    !tableColumnType.equals("NUMERIC") && !tableColumnType.equals("FLOAT4") && !tableColumnType.equals("FLOAT8")){
                notSame(difference,entityColumn,tableColumn);
            } else if(!tableColumnType.equals("INT2")){
                putIntoDifference(difference,
                        getAlterSQL(EntityAndDbDifference.ModifyDDL.LevelEnums.optimized,tableName, entityColumnName, entityTypeFullName,"数据库中[" + entityColumnName + "]字段类型["+tableColumnType+
                                "]和实体中字段类型["+entityColumnType+"]精度不一致！请修改实体字段或者执行以下SQL！"),entityColumnName);

            }
        } else if(entityColumnType.equals("INT4")){
            if( !tableColumnType.equals("INT4") && !tableColumnType.equals("INT8") &&
                    !tableColumnType.equals("NUMERIC") ){
                notSame(difference,entityColumn,tableColumn);
            } else if(!tableColumnType.equals("INT4")){
                putIntoDifference(difference,
                        getAlterSQL(EntityAndDbDifference.ModifyDDL.LevelEnums.optimized,tableName, entityColumnName, entityTypeFullName,"数据库中[" + entityColumnName + "]字段类型["+tableColumnType+
                                "]和实体中字段类型["+entityColumnType+"]精度不一致！请修改实体字段或者执行以下SQL！"),entityColumnName);

            }
        } else if (entityColumnType.equals("INT8")){
            if( !tableColumnType.equals("INT8") &&
                    !tableColumnType.equals("NUMERIC") ){
                notSame(difference,entityColumn,tableColumn);
            } else if(!tableColumnType.equals("INT8")){
                putIntoDifference(difference,
                        getAlterSQL(EntityAndDbDifference.ModifyDDL.LevelEnums.optimized,tableName, entityColumnName, entityTypeFullName,"数据库中[" + entityColumnName + "]字段类型["+tableColumnType+
                                "]和实体中字段类型["+entityColumnType+"]精度不一致！请修改实体字段或者执行以下SQL！"),entityColumnName);
            }
        } else if(entityColumnType.equals("FLOAT4") || entityColumnType.equals("FLOAT8") ){
            if(tableColumnType.equals("FLOAT4") || tableColumnType.equals("FLOAT8")){
                putIntoDifference(difference,
                        getAlterSQL(EntityAndDbDifference.ModifyDDL.LevelEnums.serious,tableName, entityColumnName, "NUMERIC(20,4)"
                                ,"数据库中[" + entityColumnName + "]使用字段类型为浮点型，可能会丢失进度！请修改实体字段为BigDecimal并执行以下SQL！"),entityColumnName);
            } else {
                putIntoDifference(difference,
                        new EntityAndDbDifference.ModifyDDL(EntityAndDbDifference.ModifyDDL.LevelEnums.serious,
                                new ArrayList<>(),"实体中[" + entityColumnName + "]使用字段类型为浮点型，可能会丢失进度！请修改实体字段为BigDecimal"),entityColumnName);
            }
        }else if(entityColumnType.equals("VARBIT")){
            if(!tableColumnType.equals("BIT") && !tableColumnType.equals("VARBIT")){
                notSame(difference,entityColumn,tableColumn);
            } else if(Misc.isNotZero(entityColumn.getMaxLength()) && Misc.isNotZero(tableColumn.getMaxLength())
                    && entityColumn.getMaxLength() > tableColumn.getMaxLength()){
                putIntoDifference(difference,
                        getAlterSQL(EntityAndDbDifference.ModifyDDL.LevelEnums.serious,tableName, entityColumnName, entityTypeFullName,"数据库中[" + entityColumnName + "]字段长度为[" + entityColumn.getMaxLength() +
                                "]比实体中约定最大长度[" + tableColumn.getMaxLength() + "]小！请修改实体字段或者执行以下SQL！"),entityColumnName);

            }
        } else if (entityColumnType.equals("NUMERIC")){
            if(tableColumnType.equals("MONEY") ){

            } else if(!tableColumnType.equals("NUMERIC") ){
                notSame(difference,entityColumn,tableColumn);
            } else if (Misc.isNotZero(entityColumn.getPrecision()) && Misc.isNotZero(tableColumn.getPrecision()) &&
                    tableColumn.getPrecision() < entityColumn.getPrecision()){
                putIntoDifference(difference,
                        getAlterSQL(EntityAndDbDifference.ModifyDDL.LevelEnums.serious,tableName, entityColumnName, entityTypeFullName,"数据库中[" + entityColumnName + "]字段类型["+tableColumn.getTypeFullName()+
                                "]和实体中字段类型["+entityColumn.getTypeFullName()+"]精度不一致！请修改实体字段或者执行以下SQL！"),entityColumnName);
            } else if (Misc.isNotZero(entityColumn.getPrecision()) && Misc.isNotZero(tableColumn.getPrecision()) &&
                    tableColumn.getPrecision() > entityColumn.getPrecision()){
                putIntoDifference(difference,
                        getAlterSQL(EntityAndDbDifference.ModifyDDL.LevelEnums.optimized,tableName, entityColumnName, entityTypeFullName,"数据库中[" + entityColumnName + "]字段类型["+tableColumn.getTypeFullName()+
                                "]和实体中字段类型["+entityColumn.getTypeFullName()+"]精度不一致！请修改实体字段或者执行以下SQL！"),entityColumnName);
            } else if (Misc.isNotZero(entityColumn.getScale()) && Misc.isNotZero(tableColumn.getScale()) &&
                    tableColumn.getScale() < entityColumn.getScale() ||
                    (Misc.isNotZero(entityColumn.getScale()) && Misc.isZero(tableColumn.getScale()))){
                putIntoDifference(difference,
                        getAlterSQL(EntityAndDbDifference.ModifyDDL.LevelEnums.serious,tableName, entityColumnName, entityTypeFullName,"数据库中[" + entityColumnName + "]字段类型["+tableColumn.getTypeFullName()+
                                "]和实体中字段类型["+entityColumn.getTypeFullName()+"]精度不一致！请修改实体字段或者执行以下SQL！"),entityColumnName);
            } else if ((Misc.isNotZero(entityColumn.getScale()) && Misc.isNotZero(tableColumn.getScale()) &&
                    tableColumn.getScale() > entityColumn.getScale()) ||
                    (Misc.isZero(entityColumn.getScale()) && Misc.isNotZero(tableColumn.getScale()))){
                putIntoDifference(difference,
                        getAlterSQL(EntityAndDbDifference.ModifyDDL.LevelEnums.optimized,tableName, entityColumnName, entityTypeFullName,"数据库中[" + entityColumnName + "]字段类型["+tableColumn.getTypeFullName()+
                                "]和实体中字段类型["+entityColumn.getTypeFullName()+"]精度不一致！请修改实体字段或者执行以下SQL！"),entityColumnName);
            }
        } else if (entityColumnType.equals("BOOL")){
            if(!tableColumnType.equals("BIT") && !tableColumnType.equals("BOOL")){
                notSame(difference,entityColumn,tableColumn);
            }
        } else if(!entityColumnType.equals(tableColumnType)){
            notSame(difference,entityColumn,tableColumn);
        }
    }

    private void notSame(EntityAndDbDifference difference, TableColumn entityColumn, TableColumn dbColumn) {
        String msg = "数据库中字段[" + dbColumn.getColumnName() + " " + dbColumn.getTypeFullName() + "]和实体["
                + entityColumn.getColumnName() + " " + entityColumn.getTypeFullName() + "]不一致！请修改实体字段或者执行以下SQL！";
        EntityAndDbDifference.ModifyDDL modifyDDL = getAlterSQL(EntityAndDbDifference.ModifyDDL.LevelEnums.serious,
                difference.getTableName(), entityColumn.getColumnName(), entityColumn.getTypeFullName(),msg);
        putIntoDifference(difference, modifyDDL,entityColumn.getColumnName());
    }

    @Override
    public String getAlterSQLTemplate(String tableName, String columnName) {
        return ALTER_SQL.replace("{tableName}", tableName)
                .replace("{columnName}", columnName);
    }
}
